home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2001 / MacHack 2001.toast / pc / The Hacks / 99 Bottles hack / MyUtils / Binhex.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-06-23  |  26.5 KB  |  1,503 lines

  1. #include "Binhex.h"
  2. #include <Errors.h>
  3.  
  4.  
  5. #define EARLYEOF -1
  6. #define BADHEXCHAR -2
  7. #define BADEOF -3
  8. #define BADPARAM -4
  9. #define    NOZERO    -5
  10. #define    USERCANCEL -6
  11.  
  12. static short vRefNum;
  13.  
  14.  
  15. static short GetSFTypeCreatorFlags(FSSpec *myFSS,long *theType,long *theCreator,unsigned short *theFlags)
  16. {
  17. short        errCode;
  18. FInfo    fndrInfo;
  19.  
  20.     *theType = 0L;
  21.     *theCreator = 0L;
  22.     *theFlags = 0;
  23.     
  24.     errCode = FSpGetFInfo(myFSS,&fndrInfo);
  25.     if (errCode == noErr)
  26.     {
  27.         *theType = fndrInfo.fdType;
  28.         *theCreator = fndrInfo.fdCreator;
  29.         *theFlags = fndrInfo.fdFlags;
  30.     }
  31.     
  32.     return(errCode);
  33. }
  34.  
  35. static short SetSFTypeCreatorFlags(FSSpec *myFSS,long theType,long theCreator,unsigned short theFlags)
  36. {
  37. short        errCode;
  38. FInfo    fndrInfo;
  39.  
  40.     errCode = FSpGetFInfo(myFSS,&fndrInfo);
  41.         
  42.     if (errCode == noErr)
  43.     {
  44.         fndrInfo.fdType = theType;
  45.         fndrInfo.fdCreator = theCreator;
  46.         fndrInfo.fdFlags = theFlags;
  47.         
  48.         errCode = FSpSetFInfo(myFSS,&fndrInfo);
  49.     }
  50.     return(errCode);
  51. }
  52.  
  53. static short GetDataForkLength(FSSpec *myFSS,long *dataForkLength)
  54. {
  55. short            errCode,fRefNum;
  56. long        byteCount;
  57.  
  58.     errCode = noErr;
  59.     *dataForkLength = 0L;
  60.     
  61.     errCode = FSpOpenDF(myFSS,0,&fRefNum);
  62.     errCode = GetEOF(fRefNum,&byteCount);
  63.     errCode = FSClose(fRefNum);
  64.  
  65.     *dataForkLength = byteCount;
  66.  
  67.     return(errCode);
  68. }
  69.  
  70. static short GetResourceForkLength(FSSpec *myFSS,long *resForkLength)
  71. {
  72. short            errCode,fRefNum;
  73. long        byteCount;
  74.  
  75.     errCode = noErr;
  76.     *resForkLength = 0L;
  77.     
  78.     errCode = FSpOpenRF(myFSS,0,&fRefNum);
  79.     errCode = GetEOF(fRefNum,&byteCount);
  80.     errCode = FSClose(fRefNum);
  81.  
  82.     *resForkLength = byteCount;
  83.  
  84.     return(errCode);
  85. }
  86.  
  87.  
  88. static short OpenAndZeroDataFork(long theType,long theCreator,FSSpec *myFSS,short *theFRefNum)
  89. {
  90. short        errCode;
  91.  
  92.     *theFRefNum = 0;
  93.     
  94.     errCode = FSpOpenDF(myFSS,0,theFRefNum);
  95.     if (errCode == fnfErr)
  96.     {
  97.         errCode = FSpCreate(myFSS,theCreator,theType,-1);
  98.         errCode = FSpOpenDF(myFSS,0,theFRefNum);
  99.     }
  100.     errCode = SetEOF(*theFRefNum,0L);
  101.     errCode = SetFPos(*theFRefNum,fsFromStart,0L);
  102.     /* Om fel,    FSClose(*theFRefNum);*theFRefNum = 0;*/
  103.  
  104.     return(errCode);
  105. }
  106.  
  107. static short OpenAndZeroResourceFork(long theType,long theCreator,FSSpec *myFSS,short *theFRefNum)
  108. {
  109.     short        errCode;
  110.     
  111.     *theFRefNum = 0;
  112.     
  113.     errCode = FSpOpenRF(myFSS,0,theFRefNum);
  114.     
  115.     if (errCode == fnfErr)
  116.     {
  117.         errCode = FSpCreate(myFSS,theCreator,theType,-1);
  118.         errCode = FSpOpenRF(myFSS,0,theFRefNum);
  119.     }
  120.     errCode = SetEOF(*theFRefNum,0L);
  121.     errCode = SetFPos(*theFRefNum,fsFromStart,0L);
  122.  
  123.     return(errCode);
  124. }
  125.  
  126.  
  127. //---
  128.  
  129. #define CR        ((unsigned char) 0x0D)
  130. #define LF        ((unsigned char) 0x0A)
  131. #define TAB        ((unsigned char) 0x09)
  132. #define SPACE     ((unsigned char) 0x20)
  133. #define RLFLAG    ((unsigned char) 0x90)
  134.  
  135. #define HEXTYPE            'TEXT'
  136. #define HEXCREATOR        '????'
  137.  
  138. #define BUFFSIZE    512
  139.  
  140. enum { PHASE62, PHASE44, PHASE26 };
  141. enum { PHASE06, PHASE24, PHASE42, PHASE60 };
  142.  
  143.  
  144.  
  145. static char                *gStartOfBinhex = "(This file must be converted with BinHex";
  146. static char                *gBinhexHeader = "(This file must be converted with BinHex 4.0)";
  147. static char                *gEndOfPart = "--- end of part";
  148. static char                gBinHexCodes[256],*gBinHexChars = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
  149. static unsigned char    *gNextHexCharPtr;
  150. static unsigned char    gCurrentReadByte,gCurrentWriteByte;
  151. static unsigned char    gPrevChar,gTheByte;
  152. static short            gChar90Count;
  153. static short            gHexPhase,gLeftIndex,gRightIndex;
  154. static unsigned short    gCRC;
  155. static char                gWriteBuffer[BUFFSIZE],gReadBuffer[BUFFSIZE];
  156. static long                gHexBytesLeftToRead,gReadBufferBytesLeft;
  157. static long                gWriteBufferIndex,gBuffer64Count;
  158. static short            gWriteFRefNum,gReadFRefNum;
  159. //static char                gSaveToDisk,gReadFromDisk;
  160. static Handle            gBinhexHandle;
  161. static long                gBinhexHandleSize,gBinhexIndex;
  162. static Ptr                gHexReadPtr;
  163.  
  164. static Callback gStartup, gProgress;
  165. static long    gTotal;
  166.  
  167.  
  168. static short GetNextReadByte(void);
  169. static short ShiftReadBuffer(void);
  170. static void CalcCRC(unsigned char theByte);
  171. static short WriteBinhexBuffer(void);
  172. static short PutByteToBinhexBuffer(void);
  173. static short FlushBinhexBuffer(void);
  174. static short SkipBreak(void);
  175. static short SkipJunkHexData(void);
  176. static short ExtractByteFromHexData(void);
  177. static short GetNextLogicalHexDataByte(char doCRC);
  178. static short FindStartOfHexData(void);
  179. static short FindEndOfHexData(void);
  180. static void SetupBinhexDataArray(void);
  181.  
  182.  
  183. static short GetNextReadByte(void)
  184. {
  185.     register short    errCode;
  186.  
  187.     errCode = noErr;
  188.     if (gHexBytesLeftToRead <= 0)
  189.     {
  190.         errCode = EARLYEOF;
  191.         return(errCode);
  192.     }
  193.     
  194.     if (gReadBufferBytesLeft <= 0)
  195.     {
  196.         if (gHexBytesLeftToRead > BUFFSIZE)
  197.             gReadBufferBytesLeft = BUFFSIZE;
  198.         else
  199.             gReadBufferBytesLeft = gHexBytesLeftToRead;
  200.         
  201.         /* Good place to update a progress bar? */
  202.         if (gProgress != NULL)
  203.         {
  204.             (*gProgress)(gTotal); // ATT FIXA: argument som anger hur långt vi kommit!
  205.             gTotal = gTotal + BUFFSIZE;
  206.         }
  207.  
  208.         errCode = FSRead(gReadFRefNum,&gReadBufferBytesLeft,(Ptr) gReadBuffer);
  209.         if (errCode != noErr)
  210.             return(errCode);
  211.  
  212.         gNextHexCharPtr = (unsigned char *) gReadBuffer;
  213.     }
  214.     
  215.     gCurrentReadByte = *gNextHexCharPtr++;
  216.     gReadBufferBytesLeft--;
  217.     gHexBytesLeftToRead--;
  218.     
  219.     return(errCode);
  220. }
  221.  
  222.  
  223. static short ShiftReadBuffer(void)
  224. {
  225. register short    errCode;
  226. long            byteCount;
  227.  
  228.     errCode = noErr;
  229.     
  230.     if (gHexBytesLeftToRead <= 0)
  231.     {
  232.         errCode = EARLYEOF;
  233.         return(errCode);
  234.     }
  235.     
  236.     if (gReadBufferBytesLeft > 0)
  237.         BlockMove((Ptr) gNextHexCharPtr,(Ptr) gReadBuffer,gReadBufferBytesLeft);
  238.     
  239.     if (gHexBytesLeftToRead > BUFFSIZE - gReadBufferBytesLeft)
  240.         byteCount = BUFFSIZE - gReadBufferBytesLeft;
  241.     else
  242.         byteCount = gHexBytesLeftToRead;
  243.     
  244.     
  245.     errCode = FSRead(gReadFRefNum,&byteCount,(Ptr) gReadBuffer + gReadBufferBytesLeft);
  246.     
  247.     if (errCode != noErr)
  248.         return(errCode);
  249.     
  250.     gNextHexCharPtr = (unsigned char *) gReadBuffer;
  251.     gReadBufferBytesLeft += byteCount;
  252.  
  253.     return(errCode);
  254. }
  255.  
  256.  
  257. // Replaced assembly with simple C code for PPC portability
  258. static void CalcCRC(unsigned char v)
  259. {
  260.     int            i;
  261.     Boolean        temp;
  262.     
  263.     for (i=1; i<=8; i++)
  264.     {
  265.         temp=((gCRC)&0x8000)!=0;
  266.         gCRC=((gCRC)<<1)|((v>>7)&0x0001);
  267.         if (temp)
  268.             (gCRC)=(gCRC)^0x1021;
  269.         v=(v<<1)&0x00ff;
  270.     }
  271. }
  272.  
  273. // A few ANSI replacements
  274.  
  275. static char * strcpy(char *dest, const char *src)
  276. {
  277.     for (;*src != 0;*dest++ = *src++);
  278.     *dest = 0;
  279. }
  280.  
  281. static long strlen(const char *s)
  282. {
  283.     long len = 0;
  284.     
  285.     for(;s[len] != 0; len++);
  286.     return len;
  287. }
  288.  
  289. static char * strcat(char *dest, const char *src)
  290. {
  291.     for (;*dest != 0; dest++);
  292.     for (;*src != 0;*dest++ = *src++);
  293.     *dest = 0;
  294. }
  295.  
  296. static char * strncpy(char * dst, const char * src, long n)
  297. {
  298.     const    char * p = src;
  299.             char * q = dst;
  300.     
  301.     n++;
  302.     
  303.     while (--n)
  304.         if (!(*q++ = *p++))
  305.         {
  306.             while (--n)
  307.                 *q++ = 0;
  308.             break;
  309.         }
  310.     
  311.     return(dst);
  312. }
  313.  
  314. static void myCtoPstr(char *s)
  315. {
  316.     char *p;
  317.     long    count;
  318.  
  319.     count = 0;
  320.     p = s;
  321.     while (*p)
  322.     {
  323.         p++;
  324.         count++;
  325.     }
  326.     BlockMove(s, &s[1], count);
  327.     s[0] = count;
  328. }
  329.  
  330.  
  331. /***************/
  332.  
  333.  
  334. static short WriteBinhexBuffer(void)
  335. {
  336. register short    errCode;
  337.  
  338.     errCode = noErr;
  339.     
  340.     errCode = FSWrite(gWriteFRefNum,&gWriteBufferIndex,(Ptr) gWriteBuffer);
  341.     gWriteBufferIndex = 0;
  342.     
  343.     return(errCode);
  344. }
  345.  
  346.  
  347. static short PutByteToBinhexBuffer(void)
  348. {
  349. register short            errCode;
  350. register unsigned char    origByte;
  351.  
  352.     errCode = noErr;
  353.     origByte = gCurrentWriteByte;
  354.     
  355.     CalcCRC(gCurrentWriteByte);
  356.         
  357.     do
  358.     {
  359.         do
  360.         {
  361.             if (gWriteBufferIndex >= BUFFSIZE - 2)
  362.             {
  363.                 errCode = WriteBinhexBuffer();
  364.                 
  365.                 if (errCode != noErr)
  366.                     return(errCode);
  367.             }
  368.             
  369.             
  370.             if (gHexPhase == PHASE06)
  371.             {
  372.                 gLeftIndex = (gCurrentWriteByte >> 2) & 0x003F;
  373.                 gRightIndex = gCurrentWriteByte;
  374.                 
  375.                 gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  376.                 
  377.                 gHexPhase = PHASE24;
  378.             }
  379.             
  380.             else if (gHexPhase == PHASE24)
  381.             {
  382.                 gLeftIndex = ((gRightIndex << 4) & 0x0030) | ((gCurrentWriteByte >> 4) & 0x000F);
  383.                 gRightIndex = gCurrentWriteByte;
  384.                 
  385.                 gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  386.                 
  387.                 gHexPhase = PHASE42;
  388.             }
  389.             
  390.             else if (gHexPhase == PHASE42)
  391.             {
  392.                 gLeftIndex = ((gRightIndex << 2) & 0x003C) | ((gCurrentWriteByte >> 6) & 0x0003);
  393.                 gRightIndex = gCurrentWriteByte;
  394.                 
  395.                 gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  396.                 
  397.                 gHexPhase = PHASE60;
  398.             }
  399.             
  400.             else if (gHexPhase == PHASE60)
  401.             {
  402.                 gLeftIndex = gRightIndex & 0x003F;
  403.                 
  404.                 gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  405.                 
  406.                 gHexPhase = PHASE06;
  407.             }
  408.             
  409.             if (++gBuffer64Count >= 64)
  410.             {
  411.                 gWriteBuffer[gWriteBufferIndex++] = '\r';
  412.                 gBuffer64Count = 0;
  413.             }
  414.             
  415.         } while (gHexPhase == PHASE06);
  416.         
  417.         if (origByte == RLFLAG)
  418.         {
  419.             if (gCurrentWriteByte == RLFLAG)
  420.                 gCurrentWriteByte = 0;
  421.             else
  422.                 origByte = 0;
  423.         }
  424.         
  425.     } while (origByte == RLFLAG);
  426.     
  427.     return(errCode);
  428. }
  429.  
  430.  
  431.  
  432. static short FlushBinhexBuffer(void)
  433. {
  434. short        errCode;
  435.  
  436.     errCode = 0;
  437.  
  438.     if (gWriteBufferIndex >= BUFFSIZE - 2)
  439.         errCode = WriteBinhexBuffer();
  440.     
  441.     gTheByte = 0;
  442.     
  443.     if (gHexPhase == PHASE24)
  444.     {
  445.         gLeftIndex = ((gRightIndex << 4) & 0x0030) | ((gTheByte >> 4) & 0x000F);
  446.         gRightIndex = gTheByte;
  447.         
  448.         gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  449.     }
  450.     
  451.     else if (gHexPhase == PHASE42)
  452.     {
  453.         gLeftIndex = ((gRightIndex << 2) & 0x003C) | ((gTheByte >> 6) & 0x0003);
  454.         gRightIndex = gTheByte;
  455.         
  456.         gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  457.     }
  458.     
  459.     else if (gHexPhase == PHASE60)
  460.     {
  461.         gLeftIndex = gRightIndex & 0x003F;
  462.         gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  463.     }
  464.     
  465.     errCode = WriteBinhexBuffer();
  466.     
  467.     return(errCode);
  468. }
  469.  
  470.  
  471.  
  472. static short SkipBreak(void)
  473. {
  474. register short            errCode,dashCount;
  475. register unsigned char     *s1,*s2;
  476.     
  477.     errCode = noErr;
  478.     
  479.     if (gCurrentReadByte == '-')
  480.     {
  481.         if (gReadBufferBytesLeft < strlen(gEndOfPart))
  482.         {
  483.             errCode = ShiftReadBuffer();
  484.             
  485.             if (errCode != noErr)
  486.                 return(errCode);
  487.         }
  488.         
  489.         s1 = (unsigned char *) gEndOfPart + 1L;
  490.         s2 = gNextHexCharPtr;
  491.         
  492.         while (*s1 == *s2 && *s1)
  493.         {
  494.             s1++;
  495.             s2++;
  496.         }
  497.         
  498.         if (*s1 == 0)
  499.         {
  500.             gNextHexCharPtr += strlen(gEndOfPart);
  501.             gReadBufferBytesLeft -= strlen(gEndOfPart);
  502.             gHexBytesLeftToRead -= strlen(gEndOfPart);
  503.             
  504.             if ((errCode = GetNextReadByte()) != noErr)
  505.                 return(errCode);
  506.             
  507.             dashCount = 0;
  508.             
  509.             while (dashCount < 3)
  510.             {
  511.                 if (gCurrentReadByte == '-')
  512.                     dashCount++;
  513.                 else
  514.                     dashCount = 0;
  515.                 
  516.                 if ((errCode = GetNextReadByte()) != noErr)
  517.                     return(errCode);
  518.             }
  519.             
  520.             dashCount = 0;
  521.             
  522.             while (dashCount < 3)
  523.             {
  524.                 if (gCurrentReadByte == '-')
  525.                     dashCount++;
  526.                 else
  527.                     dashCount = 0;
  528.                 
  529.                 if ((errCode = GetNextReadByte()) != noErr)
  530.                     return(errCode);
  531.             }
  532.             
  533.             errCode = SkipJunkHexData();
  534.         }
  535.     }
  536.  
  537.     return(errCode);
  538. }
  539.  
  540.  
  541.  
  542.  
  543. static short SkipJunkHexData(void)
  544. {
  545. register short    errCode;
  546. register unsigned char     ch;
  547.  
  548.     errCode = noErr;
  549.     
  550.     ch = gCurrentReadByte;
  551.     
  552.     if (ch == CR || ch == LF || ch == SPACE || ch == TAB)
  553.     {
  554.         do
  555.         {
  556.             if ((errCode = GetNextReadByte()) != noErr)
  557.                 return(errCode);
  558.             
  559.             ch = gCurrentReadByte;
  560.             
  561.         } while (ch == CR || ch == LF || ch == SPACE || ch == TAB);
  562.         
  563.         if (gCurrentReadByte == '-')
  564.             errCode = SkipBreak();
  565.     }
  566.  
  567.     return(errCode);
  568. }
  569.  
  570.  
  571.  
  572. static short ExtractByteFromHexData(void)
  573. {
  574. register short        errCode;
  575.  
  576.     gLeftIndex = gRightIndex;
  577.     
  578.     if ((errCode = GetNextReadByte()) != noErr)
  579.         return(errCode);
  580.     
  581.     if ((errCode = SkipJunkHexData()) != noErr)
  582.         return(errCode);
  583.     
  584.     if (gCurrentReadByte == ':')
  585.     {
  586.         errCode = EARLYEOF;
  587.         return(errCode);
  588.     }
  589.     
  590.     gRightIndex = gBinHexCodes[gCurrentReadByte];
  591.  
  592.     if (gRightIndex >= 64)
  593.     {
  594.         errCode = BADHEXCHAR;
  595.         return(errCode);
  596.     }
  597.     
  598.     if (gHexPhase == PHASE62)
  599.     {
  600.         if ((errCode = GetNextReadByte()) != noErr)
  601.             return(errCode);
  602.         
  603.         if ((errCode = SkipJunkHexData()) != noErr)
  604.             return(errCode);
  605.         
  606.         gLeftIndex = gRightIndex;
  607.         
  608.         if (gCurrentReadByte == ':')
  609.         {
  610.             errCode = EARLYEOF;
  611.             return(errCode);
  612.         }
  613.         
  614.         gRightIndex = gBinHexCodes[gCurrentReadByte];
  615.     
  616.         if (gRightIndex >= 64)
  617.         {
  618.             errCode = BADHEXCHAR;
  619.             return(errCode);
  620.         }
  621.         
  622.         gTheByte = ((gLeftIndex << 2) & 0xFC) | ((gRightIndex >> 4) & 0x03);
  623.         gHexPhase = PHASE44;
  624.     }
  625.     
  626.     else if (gHexPhase == PHASE44)
  627.     {
  628.         gTheByte = ((gLeftIndex << 4) & 0xF0) | ((gRightIndex >> 2) & 0x0F);
  629.         gHexPhase = PHASE26;
  630.     }
  631.     
  632.     else if (gHexPhase == PHASE26)
  633.     {
  634.         gTheByte = ((gLeftIndex << 6) & 0xC0) | (gRightIndex & 0x3F);
  635.         gHexPhase = PHASE62;
  636.     }
  637.     
  638.     return(errCode);
  639. }
  640.  
  641.  
  642.  
  643.  
  644. static short GetNextLogicalHexDataByte(char doCRC)
  645. {
  646. register short        errCode;
  647.  
  648.     errCode = noErr;
  649.     
  650.     if (gChar90Count > 0)
  651.     {
  652.         gTheByte = gPrevChar;
  653.         gChar90Count--;
  654.         
  655.         if (doCRC)
  656.             CalcCRC(gTheByte);
  657.         else
  658.             CalcCRC(0);
  659.     }
  660.     
  661.     else
  662.     {
  663.         do
  664.         {
  665.             errCode = ExtractByteFromHexData();
  666.             
  667.             if (gTheByte != RLFLAG)
  668.                 break;
  669.             
  670.             else
  671.             {
  672.                 errCode = ExtractByteFromHexData();
  673.                 
  674.                 if (errCode != noErr)
  675.                     return(errCode);
  676.                 
  677.                 if (gTheByte == 0)
  678.                 {
  679.                     gTheByte = RLFLAG;
  680.                     break;
  681.                 }
  682.                 
  683.                 else if (gTheByte >= 2)
  684.                 {
  685.                     gChar90Count = gTheByte - 2;
  686.                     gTheByte = gPrevChar;
  687.                     break;
  688.                 }
  689.             }
  690.         
  691.         } while (true);
  692.         
  693.         
  694.         gPrevChar = gTheByte;
  695.         
  696.         if (doCRC)
  697.             CalcCRC(gTheByte);
  698.         else
  699.             CalcCRC(0);
  700.     }
  701.  
  702.     return(errCode);
  703. }
  704.  
  705.  
  706. static short FindStartOfHexData(void)
  707. {
  708. register short    errCode,i;
  709. char            foundStart;
  710.  
  711.     errCode = noErr;
  712.     
  713.     foundStart = false;
  714.     
  715.     if ((errCode = GetNextReadByte()) != noErr)
  716.         return(errCode);
  717.     
  718.     while (!foundStart)
  719.     {
  720.         while (gCurrentReadByte != '(')
  721.         {
  722.             if ((errCode = GetNextReadByte()) != noErr)
  723.                 return(errCode);
  724.         }
  725.         
  726.         i = 0;
  727.         
  728.         while (gStartOfBinhex[i] && gCurrentReadByte == gStartOfBinhex[i])
  729.         {
  730.             if ((errCode = GetNextReadByte()) != noErr)
  731.                 return(errCode);
  732.             i++;
  733.         }
  734.         
  735.         if (gStartOfBinhex[i] == 0)
  736.         {
  737.             while (gCurrentReadByte != ':')
  738.             {
  739.                 if ((errCode = GetNextReadByte()) != noErr)
  740.                     return(errCode);
  741.             }
  742.             
  743.             foundStart = true;
  744.         }
  745.     }
  746.     
  747.     gHexPhase = PHASE62;
  748.     gPrevChar = 0;
  749.     
  750.     return(errCode);
  751. }
  752.  
  753.  
  754. static short    FindEndOfHexData(void)
  755. {
  756. register short    errCode;
  757.  
  758.     errCode = noErr;
  759.  
  760.     SkipJunkHexData();
  761.     
  762.     if ((errCode = GetNextReadByte()) != noErr)
  763.         return(errCode);
  764.     
  765.     while (gCurrentReadByte == '!')
  766.     {
  767.         SkipJunkHexData();
  768.         
  769.         if ((errCode = GetNextReadByte()) != noErr)
  770.             return(errCode);
  771.     }
  772.     
  773.     if (gCurrentReadByte != ':')
  774.     {
  775.         errCode = BADEOF;
  776.     }
  777.     
  778.     return(errCode);
  779. }
  780.  
  781.  
  782. static void SetupBinhexDataArray(void)
  783. {
  784. register short        i;
  785.  
  786.     for (i=0;i<256;i++)
  787.         gBinHexCodes[i] = 64;
  788.     
  789.     for (i=0;i<64;i++)
  790.         gBinHexCodes[gBinHexChars[i]] = i;
  791. }
  792.  
  793.  
  794. pascal short ConvertFromBinhex(FSSpec    *inFSS, Boolean deleteBinHex, Boolean deleteOld, Callback startup, Callback progress)
  795. // Boolean readFromDisk,Ptr theBinhexPtr,long dataLength)
  796. {
  797. register unsigned long    i;
  798. short                        errCode, ignoreErr;
  799. unsigned short            crc;
  800. unsigned short            theFlags;
  801. unsigned long            dataForkLength,resForkLength;
  802. Str255                    fileName;
  803. unsigned char            nameLength;
  804. long                    theType,theCreator;
  805. FSSpec                    outFSS;
  806. //StandardFileReply        theReply;
  807. FInfo                    fndrInfo;
  808.  
  809.     gReadFRefNum = 0;
  810.     gWriteFRefNum = 0;
  811.     gReadBufferBytesLeft = 0L;
  812.     gHexBytesLeftToRead = 0L;
  813.     gChar90Count = 0;
  814.     gPrevChar = 0;
  815.     
  816.     gStartup = startup;
  817.     gProgress = progress;
  818.     
  819.     SetupBinhexDataArray();
  820.         
  821.     errCode = GetDataForkLength(inFSS,&gHexBytesLeftToRead);
  822.     if (errCode != noErr)
  823.         goto BINHEXERR;
  824.  
  825.     /* Good place to update a progress bar? */
  826.     if (gStartup != NULL)
  827.         (*gStartup)(gHexBytesLeftToRead); // ATT FIXA: argument som anger hur långt vi kommit!
  828.     gTotal = 0;
  829.         
  830.     errCode = FSpOpenDF(inFSS,0,&gReadFRefNum);
  831.     if (errCode != noErr)
  832.         goto BINHEXERR;
  833.     
  834.     errCode = FindStartOfHexData();
  835.     if (errCode != noErr)
  836.         goto BINHEXERR;
  837.     
  838.     gCRC = 0;
  839.     
  840.     errCode = GetNextLogicalHexDataByte(true);
  841.     
  842.     if (errCode != noErr)
  843.         goto BINHEXERR;
  844.     
  845.     nameLength = gTheByte;
  846.     
  847.     for (i=0;i<nameLength && errCode == noErr;i++)
  848.     {
  849.         errCode = GetNextLogicalHexDataByte(true);
  850.         
  851.         if (errCode != noErr)
  852.             goto BINHEXERR;
  853.         
  854.         fileName[i] = gTheByte;
  855.     }
  856.     
  857.     errCode = GetNextLogicalHexDataByte(true);
  858.     
  859.     if (errCode != noErr)
  860.         goto BINHEXERR;
  861.     
  862.     if (gTheByte != 0)
  863.     {
  864.         errCode = NOZERO;
  865.         goto BINHEXERR;
  866.     }
  867.     
  868.     fileName[i] = gTheByte;
  869.  
  870.     theType = 0L;
  871.     
  872.     for (i=0;i<4 && errCode == noErr;i++)
  873.     {
  874.         errCode = GetNextLogicalHexDataByte(true);
  875.         
  876.         if (errCode != noErr)
  877.             goto BINHEXERR;
  878.         
  879.         theType = (theType << 8) | gTheByte;
  880.     }
  881.     
  882.     theCreator = 0L;
  883.     
  884.     for (i=0;i<4 && errCode == noErr;i++)
  885.     {
  886.         errCode = GetNextLogicalHexDataByte(true);
  887.         
  888.         if (errCode != noErr)
  889.             goto BINHEXERR;
  890.         
  891.         theCreator = (theCreator << 8) | gTheByte;
  892.     }
  893.     
  894.     errCode = GetNextLogicalHexDataByte(true);
  895.     
  896.     if (errCode != noErr)
  897.         goto BINHEXERR;
  898.     
  899.     theFlags = gTheByte;
  900.  
  901.     errCode = GetNextLogicalHexDataByte(true);
  902.     if (errCode != noErr)
  903.         goto BINHEXERR;
  904.     
  905.     theFlags = (theFlags << 8) | gTheByte;
  906.     dataForkLength = 0L;
  907.     
  908.     for (i=0;i<4 && errCode == noErr;i++)
  909.     {
  910.         errCode = GetNextLogicalHexDataByte(true);
  911.         
  912.         if (errCode != noErr)
  913.             goto BINHEXERR;
  914.         
  915.         dataForkLength = (dataForkLength << 8) | gTheByte;
  916.     }
  917.     
  918.     resForkLength = 0L;
  919.     
  920.     for (i=0;i<4 && errCode == noErr;i++)
  921.     {
  922.         errCode = GetNextLogicalHexDataByte(true);
  923.         if (errCode != noErr)
  924.             goto BINHEXERR;
  925.         
  926.         resForkLength = (resForkLength << 8) | gTheByte;
  927.     }
  928.     
  929.     errCode = GetNextLogicalHexDataByte(false);
  930.     if (errCode != noErr)
  931.         goto BINHEXERR;
  932.     
  933.     crc = gTheByte;
  934.     errCode = GetNextLogicalHexDataByte(false);
  935.     
  936.     if (errCode != noErr)
  937.         goto BINHEXERR;
  938.     
  939.     crc = (crc << 8) | gTheByte;
  940.     if (crc != gCRC)
  941.         goto BINHEXERR;
  942.     
  943.     myCtoPstr(fileName);
  944. //    StandardPutFile("\pSave File As:",fileName,&theReply);
  945.     outFSS = *inFSS;
  946.     BlockMove(fileName, outFSS.name, fileName[0]+1);
  947.  
  948. // Check if the file exists
  949.     errCode = FSpGetFInfo(&outFSS,&fndrInfo);    
  950.     
  951. // If it does exist, delete!
  952. // Mod. PhC 06/09/00
  953.     if (errCode == noErr)
  954.     {
  955.         if (deleteOld) {
  956.             errCode = FSpDelete(&outFSS);
  957.         } else {
  958.             errCode = -1; // dummy error code
  959.         }
  960. //        StandardPutFile("\pSave File As:",fileName,&theReply);
  961.  
  962. //        if (!theReply.sfGood)
  963.         if (noErr != errCode)
  964.             goto NOBINHEXERR;
  965. //        outFSS = theReply.sfFile;
  966.     }
  967.  
  968.     errCode = OpenAndZeroDataFork(theType,theCreator,&outFSS,&gWriteFRefNum);
  969.     
  970.     if (errCode != noErr)
  971.         goto BINHEXERR;
  972.     
  973.     gWriteBufferIndex = 0;
  974.     gCRC = 0;
  975.     
  976.     for (i=0;i<dataForkLength;i++)
  977.     {
  978.         errCode = GetNextLogicalHexDataByte(true);
  979.         if (errCode != noErr)
  980.             goto BINHEXERR;
  981.         
  982.         if (gWriteBufferIndex >= BUFFSIZE)
  983.         {
  984.             if (gWriteBufferIndex > 0)
  985.                 errCode = FSWrite(gWriteFRefNum,&gWriteBufferIndex,(Ptr) gWriteBuffer);
  986.             
  987.             if (errCode != noErr)
  988.                 goto BINHEXERR;
  989.             
  990.             gWriteBufferIndex = 0;
  991.         }
  992.         
  993.         gWriteBuffer[gWriteBufferIndex++] = gTheByte;
  994.     }
  995.     
  996.     if (gWriteBufferIndex > 0)
  997.     {
  998.         errCode = FSWrite(gWriteFRefNum,&gWriteBufferIndex,(Ptr) gWriteBuffer);
  999.         if (errCode != noErr)
  1000.             goto BINHEXERR;
  1001.         
  1002.         gWriteBufferIndex = 0;
  1003.     }
  1004.     
  1005.     errCode = FSClose(gWriteFRefNum);
  1006.     gWriteFRefNum = 0;
  1007.     if (errCode != noErr)
  1008.         goto BINHEXERR;
  1009.     
  1010.     errCode = GetNextLogicalHexDataByte(false);
  1011.     if (errCode != noErr)
  1012.         goto BINHEXERR;
  1013.     
  1014.     crc = gTheByte;
  1015.     
  1016.     errCode = GetNextLogicalHexDataByte(false);
  1017.     if (errCode != noErr)
  1018.         goto BINHEXERR;
  1019.     
  1020.     crc = (crc << 8) | gTheByte;
  1021.     
  1022.     if (crc != gCRC)
  1023.     {
  1024.         goto BINHEXERR;
  1025.     }
  1026.  
  1027.     errCode = OpenAndZeroResourceFork(theType,theCreator,&outFSS,&gWriteFRefNum);
  1028.     
  1029.     if (errCode != noErr)
  1030.         goto BINHEXERR;
  1031.     
  1032.     gWriteBufferIndex = 0;
  1033.     gCRC = 0;
  1034.     
  1035.     for (i=0;i<resForkLength;i++)
  1036.     {
  1037.         errCode = GetNextLogicalHexDataByte(true);
  1038.         if (errCode != noErr)
  1039.             goto BINHEXERR;
  1040.         
  1041.         if (gWriteBufferIndex >= BUFFSIZE)
  1042.         {
  1043.             if (gWriteBufferIndex > 0)
  1044.                 errCode = FSWrite(gWriteFRefNum,&gWriteBufferIndex,(Ptr) gWriteBuffer);
  1045.             
  1046.             if (errCode != noErr)
  1047.             {
  1048.                 goto BINHEXERR;
  1049.             }
  1050.             gWriteBufferIndex = 0;
  1051.         }
  1052.         gWriteBuffer[gWriteBufferIndex++] = gTheByte;
  1053.     }
  1054.     
  1055.     
  1056.     if (gWriteBufferIndex > 0)
  1057.     {
  1058.         errCode = FSWrite(gWriteFRefNum,&gWriteBufferIndex,(Ptr) gWriteBuffer);
  1059.         
  1060.         if (errCode != noErr)
  1061.         {
  1062.             goto BINHEXERR;
  1063.         }
  1064.         gWriteBufferIndex = 0;
  1065.     }
  1066.     
  1067.     errCode = FSClose(gWriteFRefNum);
  1068.     gWriteFRefNum = 0;
  1069.     
  1070.     if (errCode != noErr)
  1071.     {
  1072.         goto BINHEXERR;
  1073.     }
  1074.     
  1075.     errCode = GetNextLogicalHexDataByte(false);
  1076.     if (errCode != noErr)
  1077.         goto BINHEXERR;
  1078.     
  1079.     crc = gTheByte;
  1080.     
  1081.     errCode = GetNextLogicalHexDataByte(false);
  1082.     if (errCode != noErr)
  1083.         goto BINHEXERR;
  1084.     
  1085.     crc = (crc << 8) | gTheByte;
  1086.     
  1087.     if (crc != gCRC)
  1088.     {
  1089.         goto BINHEXERR;
  1090.     }
  1091.     
  1092.     errCode = FindEndOfHexData();
  1093.     if (errCode != noErr)
  1094.         goto BINHEXERR;
  1095.     
  1096.     errCode = SetSFTypeCreatorFlags(&outFSS,theType,theCreator,theFlags);
  1097.     if (errCode != noErr)
  1098.         goto BINHEXERR;
  1099.  
  1100.     if (errCode == noErr)
  1101.         goto NOBINHEXERR;
  1102.     
  1103.     
  1104. BINHEXERR:
  1105.     
  1106. NOBINHEXERR:
  1107.  
  1108.     if (gReadFRefNum)
  1109.     {
  1110.         if (errCode == noErr)
  1111.         {
  1112.             errCode = FSClose(gReadFRefNum);
  1113.         }
  1114.         else
  1115.             ignoreErr = FSClose(gReadFRefNum);
  1116.         
  1117.         gReadFRefNum = 0;
  1118.     }
  1119.     
  1120.     if (gWriteFRefNum)
  1121.     {
  1122.         if (errCode == noErr)
  1123.         {
  1124.             errCode = FSClose(gWriteFRefNum);
  1125.         }
  1126.         else
  1127.             ignoreErr = FSClose(gWriteFRefNum);
  1128.             
  1129.         gWriteFRefNum = 0;
  1130.     }
  1131.     
  1132.     if (errCode == USERCANCEL)
  1133.         errCode = noErr;
  1134.  
  1135. // Mod. PhC 06/09/00
  1136. // delete the hqx file if required
  1137.     if (noErr == errCode) {
  1138.         if (deleteBinHex) {
  1139.             ignoreErr = FSpDelete(inFSS);
  1140.         }
  1141.     }
  1142.  
  1143. // Mod. PhC 06/09/00
  1144. // Save the newly decoded file's FSSpec in the inFSS parameter
  1145.     BlockMoveData(&outFSS, inFSS, sizeof(FSSpec));
  1146.     
  1147.     
  1148.     return(errCode);
  1149. }
  1150.  
  1151.  
  1152. pascal short ConvertToBinhex(FSSpec *inFSS, Callback startup, Callback progress)
  1153. //pascal short ConvertToBinhex(Boolean saveToDisk,Handle    *theBinhexHandle)
  1154. {
  1155. long            i;
  1156. long            dataForkLength,resForkLength;
  1157. short            errCode, ignoreErr;
  1158. FSSpec             outFSS;
  1159. unsigned short    crc;
  1160. unsigned short    theFlags;
  1161. Str255            fileName;
  1162. unsigned char    nameLength;
  1163. long            theType,theCreator;
  1164. FInfo            fndrInfo;
  1165. //StandardFileReply    theReply;
  1166.  
  1167.     gReadFRefNum = 0;
  1168.     gWriteFRefNum = 0;
  1169.     
  1170.     gStartup = startup;
  1171.     gProgress = progress;
  1172.  
  1173.     errCode = GetSFTypeCreatorFlags(inFSS,&theType,&theCreator,&theFlags);
  1174.     
  1175.     if (errCode != noErr)
  1176.         goto BINHEXERR;
  1177.     
  1178.     inFSS->name[inFSS->name[0]+1] = 0;
  1179.     strcpy(fileName, inFSS->name+1);
  1180.     
  1181.     if (strlen(fileName) >= 27)
  1182.         fileName[27] = 0;
  1183.         
  1184. //    strncat(fileName,".hqx",32);
  1185.     strcat(fileName,".hqx");
  1186.     myCtoPstr(fileName);
  1187.     outFSS = *inFSS;
  1188.     BlockMove(fileName, outFSS.name, fileName[0]+1);
  1189.  
  1190. // Check if the file exists
  1191.     errCode = FSpGetFInfo(&outFSS,&fndrInfo);
  1192.     
  1193. // If it does exist, delete!
  1194. // If it does exist, delete!
  1195. // Mod. PhC 06/09/00
  1196.     if (errCode == noErr)
  1197.     {
  1198.         errCode = FSpDelete(&outFSS);
  1199. //        StandardPutFile("\pSave File As:",fileName,&theReply);
  1200.  
  1201. //        if (!theReply.sfGood)
  1202.         if (noErr != errCode)
  1203.             goto NOBINHEXERR;
  1204. //        outFSS = theReply.sfFile;
  1205.     }
  1206.         
  1207.     errCode = OpenAndZeroDataFork(HEXTYPE,HEXCREATOR,&outFSS,&gWriteFRefNum);
  1208.         
  1209.     if (errCode != noErr)
  1210.         goto BINHEXERR;
  1211.     
  1212.     gWriteBufferIndex = 0;
  1213.     
  1214.     strncpy(gWriteBuffer,gBinhexHeader,BUFFSIZE);
  1215.     gWriteBufferIndex = strlen(gWriteBuffer);
  1216.     
  1217.     gWriteBuffer[gWriteBufferIndex++] = '\r';
  1218.     gWriteBuffer[gWriteBufferIndex++] = ':';
  1219.     
  1220.     errCode = WriteBinhexBuffer();
  1221.     
  1222.     if (errCode != noErr)
  1223.         goto BINHEXERR;
  1224.     
  1225.     gWriteBufferIndex = 0;
  1226.     gCRC = 0;
  1227.     gBuffer64Count = 1;
  1228.     gHexPhase = PHASE06;
  1229.     
  1230.     inFSS->name[inFSS->name[0]+1] = 0;
  1231.     strcpy(fileName, inFSS->name+1);
  1232.     nameLength = strlen(fileName);
  1233.     
  1234.     gCurrentWriteByte = (char) nameLength;
  1235.     
  1236.     if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1237.         goto BINHEXERR;
  1238.     
  1239.     
  1240.     for (i=0;i<=nameLength;i++)
  1241.     {
  1242.         gCurrentWriteByte = fileName[i];
  1243.         
  1244.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1245.             goto BINHEXERR;
  1246.     }
  1247.     
  1248.     
  1249.     errCode = GetSFTypeCreatorFlags(inFSS,&theType,&theCreator,&theFlags);
  1250.     
  1251.     if (errCode != noErr)
  1252.         goto BINHEXERR;
  1253.     
  1254.     
  1255.     for (i=0;i<4;i++)
  1256.     {
  1257.         gCurrentWriteByte = (theType >> 24) & 0xFF;
  1258.         
  1259.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1260.             goto BINHEXERR;
  1261.         
  1262.         theType <<= 8;
  1263.     }
  1264.     
  1265.     
  1266.     for (i=0;i<4;i++)
  1267.     {
  1268.         gCurrentWriteByte = (theCreator >> 24) & 0xFF;
  1269.         
  1270.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1271.             goto BINHEXERR;
  1272.         
  1273.         theCreator <<= 8;
  1274.     }
  1275.     
  1276.     for (i=0;i<2;i++)
  1277.     {
  1278.         gCurrentWriteByte = (theFlags >> 8) & 0xFF;
  1279.         
  1280.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1281.             goto BINHEXERR;
  1282.         
  1283.         theFlags <<= 8;
  1284.     }
  1285.     
  1286.     
  1287.     errCode = GetDataForkLength(inFSS,&dataForkLength);
  1288.     if (errCode != noErr)
  1289.         goto BINHEXERR;
  1290.  
  1291.  
  1292.     for (i=0;i<4;i++)
  1293.     {
  1294.         gCurrentWriteByte = (dataForkLength >> 24) & 0xFF;
  1295.         
  1296.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1297.             goto BINHEXERR;
  1298.         
  1299.         dataForkLength <<= 8;
  1300.     }
  1301.     
  1302.     errCode = GetResourceForkLength(inFSS,&resForkLength);
  1303.     if (errCode != noErr)
  1304.         goto BINHEXERR;
  1305.     
  1306.  
  1307.     /* Good place to update a progress bar? */
  1308.     if (gStartup != NULL)
  1309.         (*gStartup)(dataForkLength + resForkLength);
  1310.     gTotal = 0;
  1311.  
  1312.  
  1313.     for (i=0;i<4;i++)
  1314.     {
  1315.         gCurrentWriteByte = (resForkLength >> 24) & 0xFF;
  1316.         
  1317.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1318.             goto BINHEXERR;
  1319.         
  1320.         resForkLength <<= 8;
  1321.     }
  1322.     
  1323.     CalcCRC(0);
  1324.     CalcCRC(0);
  1325.     
  1326.     crc = gCRC;
  1327.     
  1328.     for (i=0;i<2;i++)
  1329.     {
  1330.         gCurrentWriteByte = (crc >> 8) & 0xFF;
  1331.         
  1332.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1333.             goto BINHEXERR;
  1334.         
  1335.         crc <<= 8;
  1336.     }
  1337.     
  1338.     
  1339.     errCode = GetDataForkLength(inFSS,&dataForkLength);
  1340.     
  1341.     if (errCode != noErr)
  1342.         goto BINHEXERR;
  1343.     
  1344.     errCode = FSpOpenDF(inFSS,0,&gReadFRefNum);
  1345.     
  1346.     if (errCode != noErr)
  1347.         goto BINHEXERR;
  1348.     
  1349.     gCRC = 0;
  1350.     gReadBufferBytesLeft = 0L;
  1351.     gHexBytesLeftToRead = dataForkLength;
  1352.     
  1353.     for (i=0;i<dataForkLength;i++)
  1354.     {
  1355.         if ((errCode = GetNextReadByte()) != noErr)
  1356.             goto BINHEXERR;
  1357.         
  1358.         gCurrentWriteByte = gCurrentReadByte;
  1359.         
  1360.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1361.             goto BINHEXERR;
  1362.     }
  1363.     
  1364.     if ((errCode = FSClose(gReadFRefNum)) != noErr)
  1365.     {
  1366.         gReadFRefNum = 0;
  1367.         goto BINHEXERR;
  1368.     }
  1369.     
  1370.     gReadFRefNum = 0;
  1371.     
  1372.     
  1373.     CalcCRC(0);
  1374.     CalcCRC(0);
  1375.     
  1376.     crc = gCRC;
  1377.     
  1378.     for (i=0;i<2;i++)
  1379.     {
  1380.         gCurrentWriteByte = (crc >> 8) & 0xFF;
  1381.         
  1382.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1383.             goto BINHEXERR;
  1384.         
  1385.         crc <<= 8;
  1386.     }
  1387.     
  1388.     
  1389.     errCode = GetResourceForkLength(inFSS,&resForkLength);
  1390.     
  1391.     if (errCode != noErr)
  1392.         goto BINHEXERR;
  1393.     
  1394.     errCode = FSpOpenRF(inFSS,0,&gReadFRefNum);
  1395.  
  1396.     if (errCode != noErr)
  1397.         goto BINHEXERR;
  1398.     
  1399.     gCRC = 0;
  1400.     gReadBufferBytesLeft = 0L;
  1401.     gHexBytesLeftToRead = resForkLength;
  1402.     
  1403.     for (i=0;i<resForkLength;i++)
  1404.     {
  1405.         if ((errCode = GetNextReadByte()) != noErr)
  1406.             goto BINHEXERR;
  1407.         
  1408.         gCurrentWriteByte = gCurrentReadByte;
  1409.         
  1410.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1411.             goto BINHEXERR;
  1412.     }
  1413.     
  1414.     
  1415.     if ((errCode = FSClose(gReadFRefNum)) != noErr)
  1416.     {
  1417.         gReadFRefNum = 0;
  1418.         goto BINHEXERR;
  1419.     }
  1420.     
  1421.     gReadFRefNum = 0;
  1422.     
  1423.     
  1424.     CalcCRC(0);
  1425.     CalcCRC(0);
  1426.     
  1427.     crc = gCRC;
  1428.     
  1429.     for (i=0;i<2;i++)
  1430.     {
  1431.         gCurrentWriteByte = (crc >> 8) & 0xFF;
  1432.         
  1433.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1434.             goto BINHEXERR;
  1435.         
  1436.         crc <<= 8;
  1437.     }
  1438.     
  1439.     
  1440.     errCode = FlushBinhexBuffer();
  1441.     
  1442.     if (errCode != noErr)
  1443.         goto BINHEXERR;
  1444.     
  1445.     
  1446.     gWriteBufferIndex = 0;
  1447.     
  1448.     gWriteBuffer[gWriteBufferIndex++] = ':';
  1449.     gWriteBuffer[gWriteBufferIndex++] = '\r';
  1450.     
  1451.     
  1452.     errCode = WriteBinhexBuffer();
  1453.     
  1454.     if (errCode != noErr)
  1455.         goto BINHEXERR;
  1456.     
  1457.     if (errCode == noErr)
  1458.         goto NOBINHEXERR;
  1459.     
  1460.     
  1461.     
  1462.     
  1463. BINHEXERR:
  1464.     if (gBinhexHandle != NULL)
  1465.     {
  1466.         DisposeHandle(gBinhexHandle);
  1467.     }
  1468.     
  1469.     gBinhexHandle = 0L;
  1470.     
  1471.     
  1472. NOBINHEXERR:
  1473.     if (gWriteFRefNum != 0)
  1474.     {
  1475.         if (errCode == noErr)
  1476.         {
  1477.             errCode = FSClose(gWriteFRefNum);
  1478.         }
  1479.         else
  1480.             ignoreErr = FSClose(gWriteFRefNum);
  1481.         
  1482.         gWriteFRefNum = 0;
  1483.     }
  1484.     
  1485.     if (gReadFRefNum != 0)
  1486.     {
  1487.         if (errCode == noErr)
  1488.         {
  1489.             errCode = FSClose(gReadFRefNum);
  1490.         }
  1491.         
  1492.         else
  1493.             ignoreErr = FSClose(gReadFRefNum);
  1494.             
  1495.         gReadFRefNum = 0;
  1496.     }
  1497.     
  1498.     if (errCode == USERCANCEL)
  1499.         errCode = noErr;
  1500.     
  1501.     return(errCode);
  1502. }
  1503.